package com.cskaoyan.javase.oop2.polymorphic10.advantage3.newdemo;

/**
 * @description: 多态的优缺点
 * @author: wuguidong@cskaoyan.onaliyun.com
 **/

/**
 * > 引例
 * - 科学家要收集动物的叫声去研究
 * - 定义猫，狗实际动物类，它们都会叫
 * - 定义收集猫、狗叫声的方法
 * - 要收集猪的声音，怎么办呢
 *  多态的优点：
 *
 * - 要实现多态，必须要继承，复用了代码，提高了程序的可维护性（继承保证）
 * - 发生多态后，同一个引用调用方法产生不同的行为
 *   - 提高了程序的简洁性和扩展性（多态保证）
 *   多态也是有缺点的
 *   注意：现在科学家不满足于研究动物去做了，转而研究人类
 *   人类是不能直接抓来，需要请过来，得加钱人家才让你研究，于是人虽然也继承动物，但是和普通动物不同，让他叫，他要加钱
 *
 *   多态的缺点：
 *      无法调用子类独有的功能
 *
 *   ClassCastException：类型转换异常
 *   原因是你在做强制类型转换时，把一个对象指向了不是它父类的引用或者自身类引用
 *
 *   - 为了保障安全，向下转型推荐使用instanceof关键字校验
 *   - 语法
 *     引用名 instanceof 类名
 *   - 这个表达式返回一个布尔类型的值
 *
 *     - true代表该引用指向的对象，是一个后面类名的对象或者子类对象
 *     - null instanceof 任何类 结果都是false
 *     主要防止空指针异常
 *
 *     注意以后做强制类型转换，一定要instanceof
 *
 */
public class NewDemo {
    public static void main(String[] args) {
       //创建实际动物类对象
        Cat cat = new Cat();
        animalShout(cat); //相当于 Animal animal = new Cat() 因为子类完全可以看成父类
        Dog dog = new Dog();
        animalShout(dog);//相当于 Animal animal = new Dog() 因为子类完全可以看成父类
        Pig pig = new Pig();
        animalShout(pig); //相当于 Animal animal = new Pig() 因为子类完全可以看成父类
        Monkey monkey = new Monkey();
        animalShout(monkey);
        //这里因为方法的多态性，于是它们分别执行子类中重写的方法
        //直接创建人类对象传入，没有加钱了
        Person p = new Person();
        animalShout(p);

    }

    //按照以往的写法 再写一个方法 太麻烦
    //需要改进。我现在不传入一个具体的动物了，我传入一个Animal
    public static void animalShout(Animal animal){
        //抓一只动物来
        //这里如果是人类，需要加钱
        //animal.addMoney(); 这里肯定是不能调用子类独有的方法的，因为编译是看左边的
        //我就需要调用，咋办？
        //这里编译器认为你传入的是一个Animal对象，于是它只让你调用父类中的成员方法
        //于是我只要告诉编译器，我不是父类对象，我就是一个子类对象，于是就可以用子类方法
        //父类的引用---->子类的引用 对于引用数据类型而言 数据类型转换的是引用，不是对象
        //子类的引用---->父类的引用 向上转型，是自动的
        //这里需要把父类引用强转成子类引用
        //这里需要判断传入的是不是人类对象，如果是就做类型转换，如果不是就不能做类型 如果不是就不需要加钱
        if (animal instanceof Person){
            Person p = (Person) animal;
            p.addMoney();
        }
        animal.shout();
        //收集研究
    }

}

class Animal{
    public void shout(){
        System.out.println("动物叫！");
    }
}

class Cat extends Animal{
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}

class Dog extends Animal{
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}

class Pig extends Animal{
    @Override
    public void shout() {
        System.out.println("猪叫");
    }
}
class Monkey extends Animal{
    @Override
    public void shout() {
        System.out.println("猴叫");
    }
}
class Person extends Animal{
    @Override
    public void shout() {
        System.out.println("人叫");
    }
    //加钱行为
    public void addMoney(){
        System.out.println("让我叫，得加钱！");
    }
}
